package com.cta.view.controller;

import java.util.ArrayList;
import java.util.List;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.cta.constant.TariffType;
import com.cta.entity.TariffAreaCode;
import com.cta.entity.TariffGroup;
import com.cta.entity.TariffRecord;
import com.cta.service.CodeLookupService;
import com.cta.service.TariffRecordService;
import com.cta.view.controller.form.TariffAreaCodeForm;
import com.cta.view.controller.form.TariffGroupForm;
import com.cta.view.controller.form.TariffNode;
import com.cta.view.json.JsonObject;
import com.cta.view.json.tree.TariffTreeNode;

@Controller
public class TariffController extends BasicController {
	@Autowired
	private TariffRecordService tariffService;
	
	@Autowired
	private CodeLookupService codeLookupService;

	@RequestMapping(value = "/saveTariffNode", method = RequestMethod.POST)
	@ResponseBody
	public JsonObject<TariffRecord> saveTariffRecord(@Valid TariffNode node, BindingResult result) {
		if(result.hasErrors()){
			return JsonObject.emptyJsonObject();
		}
		try {
			TariffRecord tariffRecord = null;
			if (node.getId() != null) {
				tariffRecord = tariffService.updateTariffRecord(node);
			} else {
				tariffRecord = tariffService.createTariffRecord(node.getName());
			}

			return JsonObject.newJsonObject(true, tariffRecord);
		} catch (Exception e) {
			log.error("Error: ", e);
			return JsonObject.emptyJsonObject();
		}
	}

	@RequestMapping(value = "/saveGroupNode", method = RequestMethod.POST)
	@ResponseBody
	public JsonObject<TariffGroup> saveGroupNode(@Valid TariffGroupForm group, BindingResult result) {
		if(result.hasErrors()){
			return JsonObject.emptyJsonObject();
		}
		try {
			TariffGroup tariffGroup = null;
			if (group.getId() != null) {
				 tariffGroup = tariffService.updateTariffGroup(group);
				 tariffGroup.setTariffRecord(null);
			} else {
				tariffGroup = tariffService.createTariffGroup(group.getName(), group.getTariffId());
			}
			return JsonObject.newJsonObject(true, tariffGroup);
		} catch (Exception e) {
			log.error("Error: ", e);
			return JsonObject.emptyJsonObject();
		}
	}

	@RequestMapping(value = "/saveAreaNode", method = RequestMethod.POST)
	@ResponseBody
	public JsonObject<TariffAreaCode> saveAreaNode(@Valid TariffAreaCodeForm areaCode, BindingResult result) {
		if(result.hasErrors()){
			return JsonObject.emptyJsonObject();
		}
		try {
			TariffAreaCode tariffAreaCode = null;
			if (areaCode.getId() != null) {
				tariffAreaCode = tariffService.updateTariffAreaCode(areaCode);
				tariffAreaCode.setTariffGroup(null);
			} else {
				tariffAreaCode = tariffService.createTariffAreaCode(areaCode);
			}
			return JsonObject.newJsonObject(true, tariffAreaCode);
		} catch (Exception e) {
			log.error("Error: ", e);
			return JsonObject.emptyJsonObject();
		}
	}
	
	@RequestMapping(value = "/cloneAreaNode", method = RequestMethod.POST)
	@ResponseBody
	public JsonObject<TariffAreaCode> cloneAreaNode(Long areaNodeId) {
		try {
			return JsonObject.newJsonObject(true, tariffService.cloneTariffAreaCode(areaNodeId));
		} catch (Exception e) {
			log.error("Error: ", e);
			return JsonObject.emptyJsonObject();
		}
	}

	@RequestMapping(value = "/listTariffs", method = RequestMethod.GET)
	@ResponseBody
	public List<TariffTreeNode> listTariffs() {
		List<TariffTreeNode> results = new ArrayList<TariffTreeNode>();
		try {
			List<TariffRecord> tariffRecords = tariffService.listTariffRecord();
			for (TariffRecord tariffRecord : tariffRecords) {
				TariffTreeNode tnode = new TariffTreeNode();
				tnode.setText(tariffRecord.getName());
				tnode.setLeaf(false);
				tnode.setId(tariffRecord.getId() + "");
				results.add(tnode);
			}
		} catch (Exception e) {
			log.error("Error: ", e);
		}
		return results;
	}

	@RequestMapping(value = "/listTariffRecord", method = RequestMethod.GET)
	@ResponseBody
	public List<TariffTreeNode> listTariffRecord(Long treeId) {
		List<TariffTreeNode> results = new ArrayList<TariffTreeNode>();
		try {
			TariffRecord tariffRecord = tariffService.getTariffRecord(treeId);
			if (tariffRecord != null) {
				TariffTreeNode tnode = new TariffTreeNode();
				tnode.setText(tariffRecord.getName());
				tnode.setExpanded(true);
				tnode.setId(tariffRecord.getId() + "");
				tnode.setObId(tariffRecord.getId());
				results.add(tnode);
				// should be load all sub tree
				List<TariffGroup> listAllTariffGroup = tariffService.listAllTariffGroup(treeId);
				if (listAllTariffGroup.size() > 0) {
					List<Long> ids = new ArrayList<Long>(listAllTariffGroup.size());
					for (TariffGroup tariffGroup : listAllTariffGroup) {
						ids.add(tariffGroup.getId());
					}
					// get all area code of all group type
					List<TariffAreaCode> listAllTariffAreaCode = tariffService.listAllTariffAreaCode(ids);
					List<TariffTreeNode> group = buildTreeNode(listAllTariffGroup, listAllTariffAreaCode);
					tnode.setChildren(new ArrayList<TariffTreeNode>(group));
				}
				if (tnode.getChildren() == null || tnode.getChildren().size() == 0) {
					tnode.setLeaf(true);
				}
			}
		} catch (Exception e) {
			log.error("Error: ", e);
		}
		return results;
	}

	private List<TariffTreeNode> buildTreeNode(List<TariffGroup> listAllTariffGroup,
			List<TariffAreaCode> listAllTariffAreaCode) {
		List<TariffTreeNode> results = new ArrayList<TariffTreeNode>();
		for (TariffGroup tariffGroup : listAllTariffGroup) {
			TariffTreeNode tn = new TariffTreeNode();
			tn.setText(tariffGroup.getName());
			tn.setExpanded(false);
			tn.setType(TariffType.GROUP.name());
			tn.setObId(tariffGroup.getId());
			tn.setId("g_" + tariffGroup.getId());
			results.add(tn);
			List<TariffTreeNode> areaCodes = new ArrayList<TariffTreeNode>();
			for (TariffAreaCode tariffAreaCode : listAllTariffAreaCode) {
				if (tariffGroup.getId().equals(tariffAreaCode.getTariffGroup().getId())) {
					TariffTreeNode tna = new TariffTreeNode();
					tna.setText(tariffAreaCode.getAreaCode() + " " + tariffAreaCode.getName());
					tna.setLeaf(true);
					tna.setType(TariffType.AREACODE.name());
					tna.setExpanded(true);
					tna.setId("a_" + tariffAreaCode.getId());
					tna.setObId(tariffAreaCode.getId());
					areaCodes.add(tna);
				}
			}
			if (areaCodes.size() == 0) {
				tn.setLeaf(true);
			}
			tn.setChildren(areaCodes);
		}
		return results;
	}
	
	@RequestMapping(value = "/loadTariffRecord", method = RequestMethod.GET)
	@ResponseBody
	public JsonObject<TariffRecord> loadTariffRecord(Long id) {
		try {
			return JsonObject.newJsonObject(true, tariffService.getTariffRecordWithDiscount(id));
		} catch (Exception e) {
			log.error("Error: ", e);
			return JsonObject.emptyJsonObject();
		}
	}
	
	@RequestMapping(value = "/loadTariffGroup", method = RequestMethod.GET)
	@ResponseBody
	public JsonObject<TariffGroup> loadTariffGroup(Long id) {
		try {
			return JsonObject.newJsonObject(true, tariffService.getTariffGroupWithDiscount(id));
		} catch (Exception e) {
			log.error("Error: ", e);
			return JsonObject.emptyJsonObject();
		}
	}
	
	@RequestMapping(value = "/loadTariffAreaCode", method = RequestMethod.GET)
	@ResponseBody
	public JsonObject<TariffAreaCode> loadTariffAreaCode(Long id) {
		try {
			TariffAreaCode tariffAreaCodeWithRate = tariffService.getTariffAreaCodeWithRate(id);
			tariffAreaCodeWithRate.setTariffGroup(null);
			return JsonObject.newJsonObject(true, tariffAreaCodeWithRate);
		} catch (Exception e) {
			log.error("Error: ", e);
			return JsonObject.emptyJsonObject();
		}
	}
	
	@RequestMapping(value = "/deleteTariffRecord")
	@ResponseBody
	public JsonObject<TariffAreaCode> deleteTariffRecord(Long id) {
		try {
			tariffService.deleteTariffRecord(id);
			return JsonObject.newJsonObject(true, null);
		} catch (Exception e) {
			log.error("Error: ", e);
			return JsonObject.emptyJsonObject();
		}
	}
	
	@RequestMapping(value = "/deleteTariffGroup")
	@ResponseBody
	public JsonObject<TariffAreaCode> deleteTariffGroup(Long id) {
		try {
			tariffService.deleteTariffGroup(id);
			return JsonObject.newJsonObject(true, null);
		} catch (Exception e) {
			log.error("Error: ", e);
			return JsonObject.emptyJsonObject();
		}
	}
	
	@RequestMapping(value = "/deleteTariffAreaCode")
	@ResponseBody
	public JsonObject<TariffAreaCode> deleteTariffAreaCode(Long id) {
		try {
			tariffService.deleteTariffAreaCode(id);
			return JsonObject.newJsonObject(true, null);
		} catch (Exception e) {
			log.error("Error: ", e);
			return JsonObject.emptyJsonObject();
		}
	}
	
	@RequestMapping(value = "/reloadConfig")
	@ResponseBody
	public JsonObject<TariffRecord> reloadConfig(Long tariffId) {
		try {
			codeLookupService.reloadConfig(tariffId);
		} catch (Exception e) {
			return JsonObject.newJsonObject(false, null);
		}
		
		return JsonObject.newJsonObject(true, null);
	}
}
